package com.example.fitnessservice.service.impl;

import com.example.fitnessservice.api.exception.CourseException;
import com.example.fitnessservice.module.dao.courseMapper.CourseMapper;
import com.example.fitnessservice.module.dao.courseMapper.CourseOrderMapper;
import com.example.fitnessservice.module.dao.courseMapper.UserCourseMapper;
import com.example.fitnessservice.module.dao.usermapper.UserBalanceMapper;
import com.example.fitnessservice.module.dao.usermapper.UserMapper;
import com.example.fitnessservice.module.pojo.CourseDetails;
import com.example.fitnessservice.module.pojo.CourseDetailsCamp;
import com.example.fitnessservice.module.pojo.CourseOrderDetails;
import com.example.fitnessservice.module.utils.GenerateOrderNo;
import com.example.fitnessservice.module.utils.TimeUtils;
import com.example.fitnessservice.service.UserCourseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author feng
 * @version 1.0
 * @&#064;description: TODO
 * @&#064;date 2022/11/24 14:06
 */
@Service
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class UserCourseServiceImpl implements UserCourseService {
    @Autowired
    UserCourseMapper userCourseMapper;
    @Autowired
    CourseMapper courseMapper;
    @Autowired
    CourseOrderMapper orderMapper;
    @Autowired
    UserBalanceMapper userBalanceMapper;
    @Autowired
    UserMapper userMapper;

    /*
    选课，首先判断是否存在该课程，如果不存咋，则无该课程，然后判断课余量，团课最大课余量为10，私教最大课余量为一
    选课，课成人数会响应+1
    课程会相应生成列表
    用户会扣取余额
    订单生成相应订单
    不包括训练营
     */
    @Override
    public boolean join(Integer userId, Integer courseId, Integer courseCampIf) {
        /*
        不能通过这种方式选训练营的课

*/

        if (courseCampIf == 1) {
            throw new RuntimeException("训练营不支持在这里选课");
        }
        if (this.getCourseInfo(userId, courseId, courseCampIf)) {
            throw new RuntimeException("不能选课");
        }
        if (this.getCourseQuantity(courseId) == 0) {
            throw new CourseException("课余量不足");

        }
        if (this.latestTimeLimit(courseId)) {
            throw new CourseException("开课前五分钟不能选课");

        }
        CourseDetails courseDetails = courseMapper.findCourseDetailsById(courseId);

        Integer coachId = courseDetails.getCourseCoachId();

        CourseOrderDetails courseOrderDetails = new CourseOrderDetails();
        Date date = new Date();
        courseOrderDetails.setOrderCoachId(coachId);

        courseOrderDetails.setOrderTime(date);
        courseOrderDetails.setOrderCourseId(courseId);
        courseOrderDetails.setOrderUserId(userId);
        courseOrderDetails.setOrderStatus(2);
        courseOrderDetails.setOrderMoney(courseDetails.getCourseMoney());
        courseOrderDetails.setOrderNo(GenerateOrderNo.generateOrderNo(userId, courseId));
        courseOrderDetails.setOrderCampIf(courseCampIf);
        if (userCourseMapper.join(userId, courseId, courseCampIf) <= 0) {
            throw new CourseException("课程添加失败");
        } else if (courseMapper.numAdd(courseId) <= 0) {
            throw new CourseException("课程容量扣减失败");
        } else if (orderMapper.generateOrder(courseOrderDetails) <= 0) {
            throw new CourseException("订单生成失败");
        } else if (userBalanceMapper.userSpend(courseDetails.getCourseMoney(), userId) <= 0) {
            throw new CourseException("余额扣除失败");
        }
        return true;
    }

    /*
    是否符合申请时间非训练营退课需求，开课前两小时可以退课，否则不能退课,true允许退课
     */
    @Override
    public boolean whetherApply(Integer courseId) {
        CourseDetails courseDetails = courseMapper.findCourseDetailsById(courseId);
        if(courseMapper.findCourseDetailsById(courseId)==null){
            throw  new CourseException("查询课程失败");
        }
        Date date = new Date();
        Date latestDropTime = TimeUtils.addMinutes(courseDetails.getCourseStartTime(), -120);

        return date.compareTo(latestDropTime) < 0;
    }

    /*

    退课
    课余量加一
    订单状态变成3，表示已退课
    余额加上原价格
     */
    @Override
    public boolean dropCourse(Integer userId, Integer courseId, Integer courseCampIf) {
        this.whetherApply(courseId);
        if(!this.whetherApply(courseId)){
            throw new CourseException("不允许申请退课");
        }
        CourseDetails courseDetails = courseMapper.findCourseDetailsById(courseId);
        if (userCourseMapper.cancelCourse(userId, courseId, courseCampIf) <= 0) {
            throw new CourseException("修改用户课程状态失败");
        } else if (courseMapper.numReduce(courseId) <= 0) {
            throw new CourseException("课容量数据增加失败");
        } else if (orderMapper.cancelOrderstatus(userId, courseId, courseCampIf) <= 0) {
            throw new CourseException("订单状态修改失败");
        } else if (userBalanceMapper.userReturn(courseDetails.getCourseMoney(), userId) <= 0) {
            throw new CourseException("退还用户金额失败");
        }
        return true;
    }

    /*
    根据用户id,课程id查询改是否又这个课程，访问数据库过滤掉状态为3的订单，如果存在该订单且状态为2，
    表示已经选了这个课程了，前端选课前会先查询该用户是否已选这个课.根据课程开始时间和当前时间比较，如果大于当前时间，则不能再选课
     true表示已选择
     */
    @Override
    public boolean getCourseInfo(Integer userId, Integer courseId, Integer courseCampIf) {
        if (orderMapper.getCourseInfo(userId, courseId, courseCampIf) != null) {
            throw new RuntimeException("已选择该课");
        }
        solveClash(userId, courseId);


        /*
        已选择课程
         */
        return false;
    }
    /*
        解决课程冲突
    */

    private void solveClash(Integer userId, Integer courseId) {
        CourseDetails course = courseMapper.findCourseDetailsById(courseId);

        List<CourseDetails> getCourseDetailsByUserId = userMapper.findUserCourse(userId);

        List<CourseDetailsCamp> userCamp = userMapper.findUserCamp(userId);
        for (CourseDetails courseDetails : getCourseDetailsByUserId) {
            if (courseDetails.getCourseStartTime().compareTo(course.getCourseStartTime()) <= 0 && courseDetails.getCourseEndTime().compareTo(course.getCourseStartTime()) >= 0) {
                throw new RuntimeException("时间冲突不能选课");
            }
            if (courseDetails.getCourseStartTime().compareTo(course.getCourseEndTime()) <= 0 && courseDetails.getCourseEndTime().compareTo(course.getCourseEndTime()) >= 0) {
                throw new RuntimeException("时间冲突不能选课");
            }
        }
        for (CourseDetailsCamp courseDetailsCamp : userCamp) {
            if (courseDetailsCamp.getCourseStartTime().compareTo(course.getCourseStartTime()) <= 0 && courseDetailsCamp.getCourseEndTime().compareTo(course.getCourseStartTime()) >= 0) {
                throw new RuntimeException("时间冲突不能选课");
            }
            if (courseDetailsCamp.getCourseStartTime().compareTo(course.getCourseEndTime()) <= 0 && courseDetailsCamp.getCourseEndTime().compareTo(course.getCourseEndTime()) >= 0) {
                throw new RuntimeException("时间冲突不能选课");
            }
        }
    }

    /*
    限制开课前五分钟不能选课
    true，当前时间+5>开课时间，不允许选课
     */
    @Override
    public boolean latestTimeLimit(Integer courseId) {
        CourseDetails courseDetailsById = courseMapper.findCourseDetailsById(courseId);
        if (courseDetailsById == null) {
            throw new CourseException("没有这门课");
        }
        Date date = new Date();
        Date latestTime = TimeUtils.addMinutes(date, 5);
        return latestTime.compareTo(courseDetailsById.getCourseStartTime()) > 0;

    }

    /*
    查询课余量
     */
    @Override
    public Integer getCourseQuantity(Integer courseId) {
        CourseDetails courseDetailsById = courseMapper.findCourseDetailsById(courseId);
        if(courseDetailsById==null) {
            throw new CourseException("没有这门课");
        }
        CourseDetails courseDetails = courseMapper.findCourseDetailsById(courseId);
        if (courseDetails.getCourseType() == 2) {
            return 10 - courseDetails.getCourseNum();
        } else {
            return 1 - courseDetails.getCourseNum();
        }
    }


}
